<template>
  <div class="password-strength w-full">
    <!-- 密码输入框 -->
    <slot name="input">
      <el-input
        v-model="password"
        type="password"
        :placeholder="placeholder"
        @input="updateStrength"
          :prefix-icon="Lock"
        show-password
      />
    </slot>
    
    <!-- 强度指示器 -->
    <div v-if="showIndicator" class="strength-indicator">
      <!-- 强度条 -->
      <div class="strength-bars flex justify-between gap-1">
        <div 
          v-for="n in maxLevel" 
          :key="n"
          class="strength-bar-bg"
        >
          <div 
            class="strength-bar-fill"
            :class="[getBarColor(n)]"
            :style="{ width: getBarWidth(n) }"
          ></div>
        </div>
      </div>
      
      <!-- 强度文字提示 -->
      <div v-if="showText&&false" class="strength-text">
        {{ strengthText }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { User, Lock } from "@element-plus/icons-vue";

const props = withDefaults(defineProps<{
  modelValue: string
  placeholder?: string
  showIndicator?: boolean
  showText?: boolean
  maxLevel?: number
  customRules?: {
    label: string
    regex: RegExp
    score: number
  }[]
}>(), {
  placeholder: '请输入密码',
  showIndicator: true,
  showText: true,
  maxLevel: 5,
  customRules: () => [
    { label: '长度≥4', regex: /^.{4,}$/, score: 1 },
    { label: '长度≥8', regex: /^.{8,}$/, score: 1 },
    { label: '小写字母', regex: /[a-z]/, score: 1 },
    { label: '大写字母', regex: /[A-Z]/, score: 1 },
    { label: '数字', regex: /\d/, score: 1 },
    { label: '特殊字符', regex: /[^a-zA-Z0-9]/, score: 1 }
  ]
})

const emit = defineEmits(['update:modelValue', 'strength-change'])

const password = ref(props.modelValue)

// 计算密码强度等级 (0-maxLevel)
const strengthLevel = computed(() => {
  if (!password.value) return 0
  
  let score = 0
  props.customRules.forEach(rule => {
    if (rule.regex.test(password.value)) {
      score += rule.score
    }
  })
  
  // 按比例映射到maxLevel
  const maxPossibleScore = props.customRules.reduce((sum, rule) => sum + rule.score, 0)
  const level = Math.ceil((score / maxPossibleScore) * props.maxLevel)
  
  return Math.min(level, props.maxLevel)
})

// 强度文本描述
const strengthText = computed(() => {
  const texts = ['极弱', '弱', '中等', '强', '非常强']
  return texts[strengthLevel.value - 1] || '无'
})

// 强度条颜色
const getBarColor = (n: number) => {
  if (!strengthLevel.value) return 'bg-gray-300'
  if (strengthLevel.value <= 2) return 'bg-red-500'    // 弱
  if (strengthLevel.value <= 3) return 'bg-yellow-500' // 中
  return 'bg-green-500'                               // 强
}

// 强度条宽度
const getBarWidth = (n: number) => {
  return n <= strengthLevel.value ? '100%' : '0'
}

// 更新强度
const updateStrength = () => {
  emit('update:modelValue', password.value)
  emit('strength-change', strengthLevel.value)
}
</script>

<style scoped lang="scss">
.password-strength {
  @apply w-full;
}

.strength-indicator {
  @apply mt-2;
}

.strength-bars {
  @apply flex gap-1;
  height: 6px;
}

.strength-bar-bg {
  @apply flex-1 h-1.5 bg-gray-200 rounded-full overflow-hidden;
  height: 6px;
}

.strength-bar-fill {
  @apply h-full transition-all duration-300 ease-out;
}

.strength-text {
  @apply text-xs mt-1 text-gray-500;
}

/* 颜色定义 */
.bg-gray-300 {
  background-color: #d1d5db;
}
.bg-red-500 {
  background-color: #ef4444;
}
.bg-yellow-500 {
  background-color: #eab308;
}
.bg-green-500 {
  background-color: #22c55e;
}
</style>